#ifndef __IO_H_
#define __IO_H_

#include <type.h>
#include <compiler.h>

static inline u8 inb(u16 port) {
    u8 data;
    asm volatile("inb %1,%0"
        : "=a"(data)
        : "d"(port));
    return data;
}

static inline u16 inw(u16 port) {
    u16 data;
    asm volatile("inw %1,%0"
        : "=a"(data)
        : "d"(port));
    return data;
}

static inline u32 inl(u16 port) {
    u32 data;
    asm volatile("inl %1,%0"
        : "=a"(data)
        : "d"(port));
    return data;
}

static inline void outb(u16 port, u8 data) {
    asm volatile("outb %0,%1"
        :
    : "a"(data), "d"(port));
}

static inline void outw(u16 port, u16 data) {
    asm volatile("outw %0,%1"
        :
    : "a"(data), "d"(port));
}

static inline void outl(u16 port, u32 data) {
    asm volatile("outl %0,%1"
        :
    : "a"(data), "d"(port));
}

static inline void insl(int port, void* addr, int cnt) {
    asm volatile("cld\n\t"
        "rep insl"
        : "=D"(addr), "=c"(cnt)
        : "d"(port), "0"(addr), "1"(cnt)
        : "memory", "cc");
}

static inline void io_delay(int counter) {
    asm volatile (
        "   test %0, %0\n"
        "   jz 1f\n"
        "2: dec %0\n"
        "   jnz 2b\n"
        "1: dec %0"::"a"(counter));
}
#endif // __IO_H_